package com.hyt.it.ogt.kq.service.gov.schedule.utils;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;

public class MatrixUtils {

    public static int[][] bitSet2Matrix(List<BitSet> bitSets, int rowNum) {
        int[][] matrix = new int[bitSets.size()][rowNum];
        for (int i = 0; i < bitSets.size(); i++) {
            for (int j = 0; j < rowNum; j++) {
                matrix[i][j] = bitSets.get(i).get(j) ? 1 : 0;
            }
        }
        return matrix;
    }

    public static List<BitSet> matrix2BitSet(int[][] matrix) {
        List<BitSet> bitSets = new ArrayList<>(matrix.length);
        for (int i = 0; i < matrix.length; i++) {
            BitSet bitSet = new BitSet(matrix[0].length);
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 1) {
                    bitSet.set(j);
                }

            }
            bitSets.add(bitSet);
        }
        return bitSets;

    }

    public static List<BitSet> matrix2BitSetReverse(int[][] matrix) {
        List<BitSet> bitSets = new ArrayList<>(matrix.length);
        for (int i = 0; i < matrix.length; i++) {
            BitSet bitSet = new BitSet(matrix[0].length);
            for (int j = 0; j < matrix[0].length; j++) {
                if (matrix[i][j] == 0 || i == j) {
                    bitSet.set(j);
                }
            }
            bitSets.add(bitSet);
        }
        return bitSets;
    }

    /**
     * 向量点相乘 double dot(double[] x, double[] y)
     * 矩阵与矩阵之积 double[][] mult(double[][] a,double[][]b)
     * 矩阵转置 double[][] transpose(double[][] a)
     * 向量和矩阵之积 double[] mult(double[] y,double[][] a)
     */
    // 向量点乘:对应元素乘积和
    public static int dot(int[] x, int[] y) {
        int a = 0;
        // 相乘条件：必须长度相等
        if (x.length != y.length) {
            // 抛出异常
            return a;
        }
        // dot 是相应元素乘积和
        for (int i = 0; i < x.length; i++) {
            a += x[i] * y[i];
        }
        return a;

    }

    // 矩阵与矩阵相乘
    /**
     * 条件：它只有在第一个矩阵的列数（column）和第二个矩阵的行数（row）相同
     * A*B=C 其中C的行数等于A的行数，C的列数等于B的列数
     *
     * 定义：一个n行m列的矩阵乘以一个m行p列的矩阵，得到的结果是一个n行p列的矩阵
     * 其中的第i行第j列位置上的数等于它前一个矩阵第i行上的m个数与后一个矩阵第j列上的m个数对应
     * 相乘后所有m个乘积的和
     */
    public static int[][] mult(int[][] a, int[][] b) {
        int M = a[0].length;// M为a的列数
        int N = a.length;// N为a的行数
        int P = b[0].length;// P为b的列数
        // Q==M 可不写
        int Q = b.length;// Q为b的行数
        int[][] c = new int[N][P];// 矩阵c取a的行数，b的列数
        // 条件是 ：a矩阵的列数等于b矩阵的行数
        if (M != P) {
            // 此处抛出异常
        }
        // 矩阵c应该是N行P列的
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < P; j++) {
                // 关键：这里的终止条件是M，也就是a的列数（其实也可以是b的行数Q 因为 Q == M）
                for (int k = 0; k < M; k++) {
                    c[i][j] += a[i][k] * b[k][j];
                }
            }
        }
        return c;
    }

    /**
     * Matrix transposition
     * 矩阵转置
     */
    public static int[][] transpose(int[][] a) {
        int[][] b = new int[a[0].length][a.length];
        for (int i = 0; i < a[0].length; i++) {
            for (int j = 0; j < a.length; j++) {
                /**
                 * 这种方法只适用于方阵，即a[N][N],如果用于a[M][N]( M!=N ),会出现越界现象
                 * double temp = a[i][j];
                 * a[i][j] = a[j][i];
                 * a[j][i] = temp;
                 */
                // 采用新建一个数组的方式来赋值内外循环条件会变成相反
                b[i][j] = a[j][i];
            }
        }
        return b;
    }

    /**
     * 向量乘以矩阵
     * 就是相当于只有一行n列的矩阵与矩阵相乘，比二维矩阵相乘少一层循环。
     */
    public static int[] mult(int[] y, int[][] a) {
        int N = y.length;
        int[] c = new int[N];
        int M = y.length;
        if (M != a[0].length) {
            // 抛出异常
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                c[i] += a[i][j] * y[i];
            }
        }
        return c;
    }

    public static void print2D(int mat[][]) {
        // Loop through all rows
        for (int i = 0; i < mat.length; i++) {
            System.out.print(i + ":  ");
            for (int j = 0; j < mat[i].length; j++) {
                System.out.print(mat[i][j] + " ");
            }
            System.out.println("");
        }
    }
}
